(part 3 of 4)

;Non-ADAMnet Serial Read Character With Timeout Check.
;     On entry, C=base port.  On exit, if the read was ok, ZF=1

and
;A=character, else ZF=0 and A=error code.  Routine retries
approximately 10
;seconds before timing out.  C is preserved.

;errors

;CHAR_DEV_TIMEOUT_ERR   EQU  25       ;parallel or serial timed
out
;CHAR_DEV_NO_PORT_ERR   EQU  26       ;no port found for parallel
or serial
;CHAR_DEV_OR_F_P_ERR    EQU  27       ;serial had
overrun/framing/parity error
;PRINTER_OFFLINE_ERR    EQU  28       ;parallel printer is
off-line

;serial baseports

;       SER68_PORT        EQU     68
;       SER76_PORT        EQU     76
;       SER84_PORT        EQU     84
;       SER92_PORT        EQU     92
;       SER_MIB21_PORT    EQU     24
;       SER_MIB22_PORT    EQU     16

;********

__READ_SER:
        PUSH HL                 ;save so we can use it for inner loop
counter
        PUSH DE                 ;save so we can use it for outer loop
counter
        PUSH AF                 ;not needed per se, but makes exits
compatible
                                ;with SER_SEND_TCHK
        INC C                   ;point to status port
        LD D,8                  ;outer loop counter
        LD A,C                  ;get baseport
        CP SER68_PORT           ;is it Eve-Orphanware?
        JR NC,EVE_OWARE_READ    ;YES

MIB2_READ:
OUTR_LP_MI_RD:
        LD HL,65535             ;inner loop counter
INNR_LP_MI_RD:
        IN A,(C)                ;check the status port
        LD E,A                  ;save it in E
        CP 255                  ;does this port even exist?
  
     JR Z,NO_PORT            ;NO

IF OFP_CHK
        AND 240                 ;YES, so 11110000 check upper 4 bits
        JR NZ,OR_FR_P_ERR       ;sorry, errors
        LD A,E                  ;check the status again
ELSE
ENDIF

        BIT 0,A                 ;is there a character to read?
        JR NZ,READ_RDY_MI       ;YES (bit set)
        DEC HL                  ;NO, so one less inner loop
        LD A,H
        OR L                    ;down to zero yet?
        JR NZ,INNR_LP_MI_RD     ;NO, so keep going on inner loop
        DEC D                   ;YES, so one less outer loop
        JR NZ,OUTR_LP_MI_RD     ;reset the inner loop and keep trying
        JR TIME_OUT             ;sorry, we've timed out!
;********
READ_RDY_MI:
        POP AF                  ;restore character
        POP DE                  ;all done with outer loop counter
        INC C
        INC C                   ;point to data port

        IN A,(C)                ;get character
RDY2:
        DEC C
        DEC C
        DEC C                   ;restore C to entry state (baseport)
        JR SET_ZF2              ;ZF=1 for ok exit, leaving A=character
;********
EVE_OWARE_READ:
OUTR_LP_EO_RD:
        LD HL,65535            ;inner loop counter
INNR_LP_EO_RD:
        IN A,(C)               ;read status port
        LD E,A                 ;save it in E
        CP 255                 ;does the port exist?
        JR Z,NO_PORT           ;NO

IF OFP_CHK
        AND 56                 ;YES, 00111000 any framing/parity/overrun
errors?
        JR NZ,OR_FR_P_ERR      ;YES, so exit
        LD A,E                 ;NO, so check status again
ELSE
ENDIF

        AND 2                  ;is there a character ready?
        JR NZ,READ_RDY_EO      ;YES, so get it
        DEC HL                 ;NO, not yet, so one less inner loop
        LD A,H
        OR L                   ;are we down to zero?
        JR NZ,INNR_LP_EO_RD    ;NO, so keep trying on inner loop
        DEC D                  ;YES, so one less outer loop
        JR NZ,OUTR_LP_EO_RD    ;not done yet, so reset inner loop and
try again
        JR TIME_OUT            ;we have timed out!
;********
READ_RDY_EO:
        POP AF                 ;restore character
        POP DE                 ;all done with big loop counter
        DEC C                  ;back up to data port
        IN A,(C)               ;read the character
        INC C                  ;restore C=status port
        JR SET_ZF2             ;ZF=1 for ok exit, leaving character in A
;********
SET_ZF:
        PUSH HL
SET_ZF2:
        LD L,A             ;save A
        XOR A              ;ZF=1
        LD A,L             ;restore A
        POP HL
        RET


;****************************************************************]

;Non-ADAMnet Serial Send Character With Timeout Check.
;Modified PR #3 routine from SmartBASIC 1.x version 20Y by
Richard F. Drushel
;Removed error jumps to force PR #0 and print error messages, and
cleaned up
;some spaghetti left over from binary patching.

;     On entry, C=base port and A=character.  On exit, if the
send was ok,
;ZF=1 and A=character, else ZF=0 and A=error code.  Routine
retries
;approximately 10 seconds before timing out.  C is preserved.

;errors:

;CHAR_DEV_TIMEOUT_ERR   EQU  25       ;parallel or serial timed
out
;CHAR_DEV_NO_PORT_ERR   EQU  26       ;no port found for parallel
or serial
;CHAR_DEV_OR_F_P_ERR    EQU  27       ;serial had
overrun/framing/parity error

__WRITE_SER:
        PUSH HL                 ;save so we can use it for inner loop
counter
        PUSH DE                 ;save so we can use it for outer loop
counter
        PUSH AF                 ;save character
        INC C                   ;make status port
        LD D,8                  ;outer loop counter
        LD A,C                  ;get baseport
        CP SER68_PORT           ;is it Eve-Orphanware?
        JR NC,EVE_OWARE_SEND    ;YES
MIB2_SEND:
OUTR_LP_MI_SND:
        LD HL,65535             ;inner loop counter
INNR_LP_MI_SND:
        IN A,(C)                ;check the status port
        LD E,A                  ;save it in E
        CP 255                  ;does this port even exist?
        JR Z,NO_PORT            ;NO

IF OFP_CHK
        AND 240                 ;YES, so 11110000 check upper 4 bits
        JR NZ,OR_FR_P_ERR       ;sorry, errors
ELSE
ENDIF
        BIT 3,E                 ;can we send a character?
        JR NZ,SEND_RDY_MI       ;YES (bit set)
        DEC HL                  ;NO, so one less inner loop
        LD A,H

        OR L                    ;down to zero yet?
        JR NZ,INNR_LP_MI_SND    ;NO, so keep going on inner loop
        DEC D                   ;YES, so one less outer loop
        JR NZ,OUTR_LP_MI_SND    ;reset the inner loop and keep trying

TIME_OUT:
        LD A,CHAR_DEV_TIMEOUT_ERR  ;say we're timed out
SER_SEND_BYE:
SER_READ_BYE:
        POP DE                  ;clear AF off stack
        POP DE                  ;the real DE
        POP HL                  ;restore HL
        DEC C                   ;restore C to entry state (baseport)
        OR A                    ;ZF=0 for error
        RET
;********
NO_PORT:
        LD A,CHAR_DEV_NO_PORT_ERR ;missing port
        JR SER_SEND_BYE           ;error exit
;********
OR_FR_P_ERR:
        LD A,CHAR_DEV_OR_F_P_ERR ;mark overrun/framing error
        JR SER_SEND_BYE          ;error exit
;********
SEND_RDY_MI:
        POP AF                  ;restore character
        POP DE                  ;all done with outer loop counter
        INC C
        INC C                   ;point to data port
        OUT (C),A               ;send it
        JR RDY2                 ;restore C, set ZF=1 and exit with
A=character
;********
EVE_OWARE_SEND:


-Rich


